#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMessageBox>
#include <QString>
 
#include "button.h"
#include <QPainter>
#include <QHBoxLayout>
#include <QDebug>
 
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
 
    m_run_flag = false;
    connect(this,&MainWindow::signalDraw,this,&MainWindow::slotDraw);
 
    connect(ui->buttonplay, SIGNAL(clicked()), this, SLOT(onPlayClicked()));
    //connect(ui->buttonstop, SIGNAL(clicked()), this, SLOT(onStopClicked()));
 
    //ui->groupVideo->installEventFilter(this);
 
    ui->inputrtsp->setText("rtsp://uer:gd123456@192.168.2.126:554/Streaming/Channels/101");
 
 
 
    ui->buttonplay->setIcon(QIcon(":/new/image/play.png"));
    ui->buttonplay->setIconSize(QSize(50,50));
    ui->buttonplay->setMinimumSize(50,50);
    ui->buttonplay->setMaximumSize(50,50);
    ui->buttonplay->setFlat(true);
 
 
 
 
    //lay->addWidget(m_pBtnSearch); //。。。。 添加按钮。。。。。。。
    //lay->setContentsMargins(0, 0, 0, 0);
    //lay->setAlignment(Qt::AlignRight);
 
    //ui->inputrtsp->setFrame(false);
    ui->inputrtsp->setStyleSheet("QLineEdit{ background-color: rgba(128,128,128,120); }QLineEdit:focus{background-color: rgb(222,222,222)}"); // 设置样式
    //ui->inputrtsp->setTextMargins(0, 0, 30, 0); // 注意这里的30  因为图一的输入框最右边有个按钮。不能让光标在此区域出现。。需要设置文字显示范围
    //searchEdit->setPlaceholderText(tr("许嵩"));  // 设置默认文字
 
 
   //ui->buttonplay->setStyleSheet("background-color: yellow");
 
   //ui->buttonstop->setStyleSheet("background-color: red");
 
 
#if 0
    MyButton *play = new MyButton(this);
    connect(play, SIGNAL(clicked()), this, SLOT(onPlayClicked()));
    play->move(100,200);
 
 
    QPushButton *test = new QPushButton(this);
    connect(test,SIGNAL(clicked()),this,SLOT(slotButtonClicked()));
    test->setText("test button");
    test->move(200,300);
 
 
 
 
    connect(ui->buttonexit, SIGNAL(clicked()), this, SLOT(onExitClicked()));
 
 
 
 
#endif
}
 
void MainWindow::closeEvent(QCloseEvent *e)
{
    QMessageBox::StandardButton result=QMessageBox::question(this, "确认", "确定要退出本程序吗？",
                          QMessageBox::Yes|QMessageBox::No,
                          QMessageBox::No);
 
        if (result==QMessageBox::Yes)
            e->accept();
        else
            e->ignore();
 
}

//初始化
int MainWindow::init()
{
    //std::string file = "rtsp://uer:gd123456@192.168.2.121:554/Streaming/Channels/101";
 
    QString file =ui->inputrtsp->text();
    //描述多媒体文件的构成及其基本信息
    pAVFormatCtx = avformat_alloc_context(); //Init handle
 
    if (avformat_open_input(&pAVFormatCtx, file.toUtf8(), NULL, NULL) != 0)
    {
        qDebug() <<"open file fail";
        avformat_free_context(pAVFormatCtx);
        return -1;
    }
 
    //读取一部分视音频数据并且获得一些相关的信息
    if (avformat_find_stream_info(pAVFormatCtx, NULL) < 0)
    {
        qDebug() <<"vformat find stream fail";
        avformat_close_input(&pAVFormatCtx);
        return -1;
    }
    // 根据解码器枚举类型找到解码器
    AVCodec *pAVCodec;
    int ret = av_find_best_stream(pAVFormatCtx, AVMEDIA_TYPE_VIDEO, -1, -1, &pAVCodec, 0);
    if (ret < 0) {
        qDebug()<< "av_find_best_stream faliture";
        avformat_close_input(&pAVFormatCtx);
        return -1;
    }
    iVideoIndex = ret;
 
    pAVCodec = avcodec_find_decoder(pAVFormatCtx->streams[iVideoIndex]->codecpar->codec_id);
    if (pAVCodec == NULL)
    {
        qDebug()<<"not find decoder";
        return -1;
    }
 
    qDebug()<<"avcodec_open2 pAVCodec->name:" << QString::fromStdString(pAVCodec->name);
 
 
    if(pAVFormatCtx->streams[iVideoIndex]->avg_frame_rate.den != 0) {
        float fps_ = pAVFormatCtx->streams[iVideoIndex]->avg_frame_rate.num / pAVFormatCtx->streams[iVideoIndex]->avg_frame_rate.den;
        qDebug() <<"fps:" << fps_;
    }
    int64_t video_length_sec_ = pAVFormatCtx->duration/AV_TIME_BASE;
    qDebug() <<"video_length_sec_:" << video_length_sec_;
    pAVCodecCtx = avcodec_alloc_context3(pAVCodec);
    if (pAVCodecCtx == NULL)
    {
        qDebug() <<"get pAVCodecCtx fail";
        avformat_close_input(&pAVFormatCtx);
        return -1;
    }
    ret = avcodec_parameters_to_context(pAVCodecCtx,pAVFormatCtx->streams[iVideoIndex]->codecpar);
    if (ret < 0)
    {
        qDebug() <<"avcodec_parameters_to_context fail";
        avformat_close_input(&pAVFormatCtx);
        return -1;
    }
    if (avcodec_open2(pAVCodecCtx, pAVCodec, NULL) < 0)
    {
        qDebug()<<"avcodec_open2 fail";
        return -1;
    }
    //为解码帧分配内存
    //AVFrame 存放从AVPacket中解码出来的原始数据
    pAVFrame = av_frame_alloc();
    pAVFrameRGB = av_frame_alloc();
    //用于视频图像的转换,将源数据转换为RGB32的目标数据
    pSwsCtx = sws_getContext(pAVCodecCtx->width, pAVCodecCtx->height, pAVCodecCtx->pix_fmt,
                            pAVCodecCtx->width, pAVCodecCtx->height, AV_PIX_FMT_RGB32,
                            SWS_BICUBIC, NULL, NULL, NULL);
 
    int  m_size = av_image_get_buffer_size(AVPixelFormat(AV_PIX_FMT_RGB32), pAVCodecCtx->width, pAVCodecCtx->height, 1);
    pRgbBuffer = (uint8_t *)(av_malloc(m_size));
    //为已经分配的空间的结构体AVPicture挂上一段用于保存数据的空间
    avpicture_fill((AVPicture *)pAVFrameRGB, pRgbBuffer, AV_PIX_FMT_BGR32, pAVCodecCtx->width, pAVCodecCtx->height);
    //av_image_fill_arrays
    //AVpacket 用来存放解码数据
    av_new_packet(&packet, pAVCodecCtx->width * pAVCodecCtx->height);
    return 0;
}
 
void MainWindow::play()
{
    m_decodecThread = std::thread([this]()
    {
        init();
        decodec();
    });
    m_decodecThread.detach();
}

//解码
void MainWindow::decodec()
{
    //读取码流中视频帧
        while (m_run_flag)
        {
            int ret = av_read_frame(pAVFormatCtx, &packet);
            if(ret != 0)
            {
                qDebug()<<"file end";
                isFinish = !isFinish;
                 return;
            }
            if (packet.stream_index != iVideoIndex)
            {
                av_packet_unref(&packet);
                continue;
            }
           int iGotPic = AVERROR(EAGAIN);
//             //解码一帧视频数据
            iGotPic = avcodec_send_packet(pAVCodecCtx, &packet);
            if(iGotPic!=0){
                qDebug()<<"avcodec_send_packet error";
                      continue;
            }
            iGotPic = avcodec_receive_frame(pAVCodecCtx, pAVFrame);
   if(iGotPic == 0){
                   //转换像素
                   sws_scale(pSwsCtx, (uint8_t const * const *)pAVFrame->data, pAVFrame->linesize, 0, pAVCodecCtx->height, pAVFrameRGB->data, pAVFrameRGB->linesize);
 
                   //构造QImage
                   QImage img(pRgbBuffer, pAVCodecCtx->width, pAVCodecCtx->height, QImage::Format_RGB32);
                   //qDebug()<<"decode img";
                   m_image = img;
                   emit signalDraw();
  }else {
           qDebug()<<"decode error";
           }
 
            av_packet_unref(&packet);
            //std::this_thread::sleep_for(std::chrono::milliseconds(25));
        }
  //资源回收
        av_free(pAVFrame);
        av_free(pAVFrameRGB);
        sws_freeContext(pSwsCtx);
        avcodec_close(pAVCodecCtx);
        avformat_close_input(&pAVFormatCtx);
}
 
void MainWindow::slotDraw()
{
    update();
}
 
void MainWindow::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.setBrush(Qt::black);
    painter.drawRect(0, 0, this->width(), this->height());
 
 
 
    int appWindowWidth = this->geometry().width();
 
    int appWindowHeight = this->geometry().height();
 
 
    int button_w = ui->buttonplay->geometry().width();
    int button_h = ui->buttonplay->geometry().height();
 
 
    int intpu_w = ui->groupInput->geometry().width();
    int input_h = ui->groupInput->geometry().height();
 
 
    auto center_x = (appWindowWidth-button_w)/2;
    auto center_y = (appWindowHeight-button_h-50);
 
    ui->buttonplay->setGeometry(center_x, center_y, button_w,button_h);
 
 
 
    center_x = (appWindowWidth-intpu_w)/2;
    center_y = (appWindowHeight-input_h-120);
 
    ui->groupInput->setGeometry(center_x, center_y, intpu_w,input_h);
 
 
    if(m_run_flag == false)
    {
        return ;
    }
 
    if (m_image.size().width() <= 0)
        return;
 
    //比例缩放
    QImage img = m_image.scaled(this->size(),Qt::KeepAspectRatio);
    int x = this->width() - img.width();
    int y = this->height() - img.height();
 
    x /= 2;
    y /= 2;
 
    //QPoint(x,y)为中心绘制图像
    painter.drawImage(QPoint(x,y),img);
}

void MainWindow::slotButtonClicked()
{
    QMessageBox::information(NULL,"Click","Double click",QMessageBox::Accepted);
}
 
void MainWindow::onPlayClicked()
{
    if(m_run_flag == false)
    {
 
        ui->buttonplay->setIcon(QIcon(":/new/image/stop.png"));
        ui->buttonplay->setIconSize(QSize(50,50));
        ui->buttonplay->setMinimumSize(50,50);
        ui->buttonplay->setMaximumSize(50,50);
        ui->buttonplay->setFlat(true);
        m_run_flag = true;
 
        play();
    }
    else
    {
        m_run_flag = false;
        ui->buttonplay->setIcon(QIcon(":/new/image/play.png"));
        ui->buttonplay->setIconSize(QSize(50,50));
        ui->buttonplay->setMinimumSize(50,50);
        ui->buttonplay->setMaximumSize(50,50);
        ui->buttonplay->setFlat(true);
        //QMessageBox::information(NULL,"Click","Allready in playing...",QMessageBox::Accepted);
    }
}
 
void MainWindow::onExitClicked()
{
    QMessageBox::information(NULL,"Click","onexitClicked",QMessageBox::Accepted);
    //ui->buttonexit->setText("I am exit button");
}
 
void MainWindow::onStopClicked()
{
    //QMessageBox::information(NULL,"Click","onStopClicked",QMessageBox::Accepted);
    m_run_flag = false;
    update();
    //qApp->exit();
}
 
void MainWindow::mouseDoubleClickEvent( QMouseEvent * e )
{
    if ( e->button() == Qt::LeftButton )
    {
        m_fullscreen_flag = 1-m_fullscreen_flag;
        if(m_fullscreen_flag)
        {
            showFullScreen();
        }
        else
        {
            showNormal();
        }
    }
    // You may have to call the parent's method for other cases
    QMainWindow::mouseDoubleClickEvent( e );
}
 
MainWindow::~MainWindow()
{
    m_run_flag = false;
    delete ui;
}